package com.vegetable.modules.service.outbound.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vegetable.common.constant.CommonConstant;
import com.vegetable.common.annotation.SalesCustomerPermission;
import com.vegetable.common.utils.Constant;
import com.vegetable.common.utils.PageUtils;
import com.vegetable.common.utils.Query;
import com.vegetable.common.utils.R;
import com.vegetable.modules.entity.baseData.AddressBook;
import com.vegetable.modules.entity.baseData.ProductSpec;
import com.vegetable.modules.entity.baseData.Products;
import com.vegetable.modules.entity.inbound.AgentDelivery;
import com.vegetable.modules.entity.inbound.AgentDeliveryDetail;
import com.vegetable.modules.entity.inbound.PackDelivery;
import com.vegetable.modules.entity.inbound.PackDeliveryDetail;
import com.vegetable.modules.entity.outbound.*;
import com.vegetable.modules.entity.outbound.po.*;
import com.vegetable.modules.entity.outbound.vo.CustomerPurchaseAnalysisVO;
import com.vegetable.modules.entity.outbound.vo.NoCostWeightListVO;
import com.vegetable.modules.entity.stock.Stock;
import com.vegetable.modules.entity.sys.SysUserEntity;
import com.vegetable.modules.mapper.outbound.SalesOrderMapper;
import com.vegetable.modules.mapper.outbound.SalesOrderTransmitMapper;
import com.vegetable.modules.service.baseData.IAddressBookService;
import com.vegetable.modules.service.baseData.IProductSpecService;
import com.vegetable.modules.service.baseData.IProductsService;
import com.vegetable.modules.service.baseData.ITrainNumRecordService;
import com.vegetable.modules.service.inbound.IAgentDeliveryDetailService;
import com.vegetable.modules.service.inbound.IAgentDeliveryService;
import com.vegetable.modules.service.inbound.IPackDeliveryDetailService;
import com.vegetable.modules.service.inbound.IPackDeliveryService;
import com.vegetable.modules.service.outbound.*;
import com.vegetable.modules.service.stock.IStockFlowService;
import com.vegetable.modules.service.stock.IStockService;
import com.vegetable.modules.service.sys.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.Collator;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 销售订货 服务实现类
 * </p>
 *
 * @author wangruijie
 * @since 2024-03-27
 */
@Slf4j
@Service
//@AllArgsConstructor
public class SalesOrderServiceImpl extends ServiceImpl<SalesOrderMapper, SalesOrder> implements ISalesOrderService {

    // 销售订货商品明细表
    @Autowired
    private ISalesOrderDetailService detailService;
    // 销售订货商品明细库存对照表
    @Autowired
    private ISalesOrderDetailStockService detailStockService;
    // 销售订货任务下达表
    @Autowired
    private SalesOrderTransmitMapper transmitMapper;
    // 销售出库
    @Autowired
    private ISalesOutService salesOutService;
    // 库存表
    @Autowired
    private IStockService stockService;
    // 代办交货
    @Autowired
    private IAgentDeliveryService agentDeliveryService;
    @Autowired
    private IAgentDeliveryDetailService agentDeliveryDetailService;
    // 产地商品
    @Autowired
    private IProductsService productsService;
    @Autowired
    private SysUserService userService;
    @Autowired
    private IPackDeliveryService packDeliveryService;
    // 库存流水
    @Autowired
    private IStockFlowService iStockFlowService;
    @Autowired
    private IPackDeliveryDetailService packDeliveryDetailService;
    @Autowired
    private ITrainNumRecordService iTrainNumRecordService;
    @Autowired
    private ISalesOutDetailService iSalesOutDetailService;
    @Autowired
    private IProductSpecService productSpecService;
    @Autowired
    private IAddressBookService iAddressBookService;

    public SalesOrderServiceImpl() {
    }

    /**
     * 销售订货列表查询
     * @param params
     * @return
     */
    @Override
    @SalesCustomerPermission(type = SalesCustomerPermission.PermissionType.CUSTOMER)
    public PageUtils queryPage(Map<String, Object> params) {
        String docNo = (String)params.get("docNo");
        Object state = params.get("state");
        List<Object> states = new ArrayList<>();
        if (Integer.valueOf(state.toString()) == 1){
            states = Arrays.asList(state, 2);
        }else {
            states = Collections.singletonList(state);
        }
        String startTime = (String)params.get("startTime");
        String endTime = (String)params.get("endTime");
        QueryWrapper<SalesOrder> queryWrapper = new QueryWrapper<SalesOrder>()
                .between(StringUtils.isNotBlank(startTime), "order_time", startTime, endTime)
                .in(ObjectUtils.isNotEmpty(state),"state", states)
                .eq(ObjectUtils.isNotEmpty(params.get("customerId")),"customer_id", params.get("customerId"))
                .eq(ObjectUtils.isNotEmpty(params.get("regionId")),"region_id", params.get("regionId"))
                .like(StringUtils.isNotBlank(docNo),"doc_no", docNo)
                .orderByDesc("create_time");
        
        // 处理数据权限控制的客户ID过滤
        if (params.containsKey("customerIds")) {
            Object customerIds = params.get("customerIds");
            if (customerIds instanceof List) {
                queryWrapper.in("customer_id", (List<?>) customerIds);
            }
        } else if (ObjectUtils.isNotEmpty(params.get("customerId"))) {
            queryWrapper.eq("customer_id", params.get("customerId"));
        }
        
        IPage<SalesOrder> page = this.page(
                new Query<SalesOrder>().getPage(params),
                queryWrapper
        );
        if (CollectionUtils.isNotEmpty(page.getRecords())){
            // 创建用户id集合
            List<Long> createUserIds = page.getRecords().stream().map(el -> el.getCreateUserId()).collect(Collectors.toList());
            List<Long> orderIds = page.getRecords().stream().map(el -> el.getId()).collect(Collectors.toList());
            QueryWrapper<SalesOrderDetail> wrapper = new QueryWrapper<>();
            wrapper.in("sales_id", orderIds);
            List<SalesOrderDetail> allDetails = detailService.getBaseMapper().selectList(wrapper);
            for(Long orderId : orderIds){
                SalesOrder order = page.getRecords().stream().filter(el -> el.getId().equals(orderId)).findAny().get();
                List<SalesOrderDetail> details = allDetails.stream().
                        filter(el -> el.getSalesId().equals(orderId)).
                        filter(el -> !NumberUtil.equals(el.getNumber(), el.getShiftNumber())).
                        collect(Collectors.toList());

                if(CollectionUtil.isNotEmpty(details)){
                    order.setIsAllShift(1);
                    order.setShiftInfo(details);
                }else{
                    order.setIsAllShift(0);
                }
            }
            List<SysUserEntity> userList = userService.listByIds(createUserIds);
            for(SalesOrder order : page.getRecords()){
                Long currentUserId = order.getCreateUserId();
                Optional<SysUserEntity> cu = userList.stream().filter(el -> el.getUserId().equals(currentUserId)).findAny();
                cu.ifPresent(sysUserEntity -> order.setCreateUserName(sysUserEntity.getRealName()));
            }
//            for (SalesOrder order:page.getRecords()) {
//                SysUserEntity userEntity = userService.getById(order.getCreateUserId());
//                order.setCreateUserName(userEntity.getRealName());
//                List<SalesOrderDetail> details = detailService.allShift(order.getId());
//                if(CollectionUtil.isNotEmpty(details)){
//                    order.setIsAllShift(1);
//                    order.setShiftInfo(details);
//                }else{
//                    order.setIsAllShift(0);
//                }
//            }
        }
        return new PageUtils(page);
    }

    /**
     * 销售走货列表
     * @param params
     * @return
     */
    @Override
    public PageUtils salesOrderList(Map<String, Object> params) {
        String commodityName = (String) params.get("commodityName");
        IPage<SalesOrderDetail> page = detailService.page(
                new Query<SalesOrderDetail>().getPage(params),
                new QueryWrapper<SalesOrderDetail>()
                        .like(StringUtils.isNotBlank(commodityName),"commodity_name", commodityName)
                        .eq(ObjectUtils.isNotEmpty(params.get("customerId")),"customer_id", params.get("customerId"))
        );

        List<SalesOrderDetail> records = page.getRecords();
        if (CollectionUtils.isNotEmpty(records)){
            for (SalesOrderDetail detail:records) {
                SalesOrder salesOrder = baseMapper.selectById(detail.getSalesId());
                detail.setDocNo(salesOrder.getDocNo());
                List<SalesOrderDetailStock> detailStocks = detailStockService.getBaseMapper().selectList(Wrappers.<SalesOrderDetailStock>query().lambda().eq(SalesOrderDetailStock::getDetailId, detail.getId()));
                detail.setStocks(detailStocks);
            }
            page.setRecords(records);
        }
        return new PageUtils(page);

    }

    /**
     * 复制销售订货
     * @param id null
     * @return R
     * @author wrj
     * @since 2024/3/29 上午11:42
     */
    @Override
    public R copySalesOrder(Long id, Long createUserId) throws Exception {
        SalesOrder salesOrder = new SalesOrder();
        salesOrder.setState(1);
        salesOrder.setCreateUserId(createUserId);
        // 查询原订单的商品
        List<SalesOrderDetail> details = detailService.selectByOrderId(id);
        if (CollectionUtils.isNotEmpty(details)){
            for (SalesOrderDetail detail:details) {
                detail.setSalesId(null);
                detail.setId(null);
                detail.setNumber(0);
                detail.setStartNumber(0);
                detail.setShiftNumber(0);
                detail.setStockNumber(0);
                detail.setWeight(BigDecimal.ZERO);
                detail.setStockWeight(BigDecimal.ZERO);
                detail.setStartWeight(BigDecimal.ZERO);
                detail.setShiftWeight(BigDecimal.ZERO);
            }
            salesOrder.setCommodities(details);
        }
        return saveSalesOrder(salesOrder);
    }

    /**
     * 详情销售订货
     * @param id null
     * @return R
     * @author wrj
     * @since 2024/3/27 下午4:35
     */
    @Override
    public R detailSalesOrder(Long id) {
        SalesOrder salesOrder = baseMapper.selectById(id);
        if (salesOrder == null){
            return R.fail("订单不存在");
        }
        // 查询原订单的商品
//        QueryWrapper<SalesOrderDetail> detailQuery = new QueryWrapper();
//        detailQuery.eq("sales_id", salesOrder.getId());
//        detailQuery.orderByAsc("sort", "id");
        List<SalesOrderDetail> details = detailService.selectByOrderIdInCloudStock(id);
        List<Long> detailIds = details.stream().map(el -> el.getId()).collect(Collectors.toList());
        List<SalesOrderDetailStock> stockList = detailStockService.selectByDetailIds(detailIds);
        Map<Long, List<SalesOrderDetailStock>> listMap = stockList.stream().collect(Collectors.groupingBy(SalesOrderDetailStock::getDetailId));

//        if (CollectionUtils.isNotEmpty(details)){
            for (SalesOrderDetail detail : details) {
                List<SalesOrderDetailStock> detailStocks = listMap.get(detail.getId());
                detailStocks = CollectionUtil.isNotEmpty(detailStocks) ? detailStocks : new ArrayList<>();
//                Products products = productsService.getById(detail.getCommodityId());
//                if(ObjectUtil.isNull(products)){
//                    log.error("根据商品id{}找不到商品啦！！！！", detail.getCommodityId());
//                    continue;
//                }
//                detail.setCommodityCode(products.getCommonCode());
//                List<SalesOrderDetailStock> stockList = detailStockService.getBaseMapper().selectList(Wrappers.<SalesOrderDetailStock>query().lambda().eq(SalesOrderDetailStock::getDetailId, detail.getId()));
                detail.setStocks(detailStocks);
//                List<Stock> stocks = stockService.selectGoodsStock(detail.getCommodityId(), detail.getSpecsId());
//                if(CollectionUtil.isNotEmpty(stocks)){
//                    detail.setStockNumber(stocks.stream().mapToInt(e -> e.getNumber()).sum());
//                    detail.setStockWeight(stocks.stream().map(e -> e.getWeight()).reduce(BigDecimal.ZERO, BigDecimal::add));
//                }
//            }
//            salesOrder.setCommodities(details);
        }
        salesOrder.setCommodities(details);
        return R.data(salesOrder);
    }

    /**
     * 根据id查询详组装发货数据（销售出库单）
     * @param id null
     * @return R
     * @author wrj
     * @since 2024/4/1 下午9:30
     */
    @Override
    @Transactional
    public R<SalesOut> buildSendGoods(Long id) throws Exception {
        // 销售出库主表
        SalesOut salesOut = new SalesOut();
        SalesOrder salesOrder = baseMapper.selectById(id);
        if (salesOrder == null){
            return R.fail("销售订货不存在");
        }
        // 如果销售单状态是1（未发货），则改成2（已发货）
        if(salesOrder.getState() == 1){
            SalesOrder updater = new SalesOrder();
            updater.setId(id);
            updater.setState(2);
            baseMapper.updateById(updater);
        }
        /*if (salesOrder.getState().intValue() != 1){
            return R.fail("销售订货还未走货不能发货");
        }*/
        // 存在销售出库单则直接返回
        SalesOut out = salesOutService.getBaseMapper().selectOne(Wrappers.<SalesOut>query().lambda().eq(SalesOut::getSalesOrderId, id));
        if (out != null){
//            return salesOutService.detailSalesOut(out.getId());
            throw new Exception("订单已出库哦～");
        }
        salesOut.setSalesOrderId(salesOrder.getId());
        salesOut.setOrderTime(salesOrder.getOrderTime());
        // 订单来源0订货发货，1新建
        salesOut.setOrderSource(0);
        salesOut.setState(0);
        salesOut.setCustomerId(salesOrder.getCustomerId());
        salesOut.setCustomerName(salesOrder.getCustomerName());
        salesOut.setNumber(salesOrder.getNumber());
        salesOut.setWeight(salesOrder.getWeight());
        salesOut.setRegionId(salesOrder.getRegionId());
        List<SalesOutDetail> commodities = new ArrayList<>();
        // 查询原订单的商品
        QueryWrapper<SalesOrderDetail> detailQuery = new QueryWrapper();
        detailQuery.eq("sales_id", id);
        detailQuery.orderByAsc("sort", "id");
        List<SalesOrderDetail> details = detailService.getBaseMapper().selectList(detailQuery);
        if (CollectionUtils.isNotEmpty(details)){
            for (SalesOrderDetail detail:details) {
                SalesOutDetail outDetail = new SalesOutDetail();
                outDetail.setIsFruit(1);
                outDetail.setCommodityId(detail.getCommodityId());
                outDetail.setCommodityName(detail.getCommodityName());
                outDetail.setCommodityCode(detail.getCommodityCode());
                outDetail.setSpecsId(detail.getSpecsId());
                outDetail.setSpecsName(detail.getSpecsName());
                outDetail.setStandard(detail.getStandard());
                outDetail.setNumber(ObjectUtil.isNull(detail.getShiftNumber()) || detail.getShiftNumber() == 0 ? detail.getNumber() : detail.getShiftNumber() );
                outDetail.setWeight(ObjectUtil.isNull(detail.getShiftWeight()) || NumberUtil.equals(detail.getShiftWeight(), BigDecimal.ZERO) ? detail.getWeight() : detail.getShiftWeight() );
//                outDetail.setOutNumber(0);
//                outDetail.setOutWeight(BigDecimal.ZERO);
                outDetail.setMode(0);
                List<SalesOrderDetailStock> detailStocks = detailStockService.getBaseMapper().selectList(Wrappers.<SalesOrderDetailStock>query().lambda().eq(SalesOrderDetailStock::getDetailId, detail.getId()));
                outDetail.setStocks(detailStocks);
                outDetail.setOrderDetailId(detail.getId());
                commodities.add(outDetail);
            }
        }
        salesOut.setCommodities(commodities);
        salesOutService.saveSalesOut(salesOut);
        Integer trainNum = iTrainNumRecordService.queryTrainNum(salesOrder.getCustomerId());
        salesOut.setTrainNum( (trainNum + 1) + "");
        // 开始计算成本
        log.info("{}发货，开始出库并计算成本", id);
        salesOutService.checkOrderCostByOrderId(id);
        return R.data(salesOut);
    }

    /**
     * 新增销售订货
     * @param salesOrder null
     * @return R
     * @author wrj
     * @since 2024/3/27 下午4:35
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R saveSalesOrder(SalesOrder salesOrder) throws Exception {

        List<SalesOrderDetail> commodities1 = salesOrder.getCommodities();
        if (CollectionUtils.isEmpty(commodities1)){
            throw new Exception("商品列表不能为空");
        }
        List<SalesOrderDetail> currentCommodities = new ArrayList<>();
        for(SalesOrderDetail detail : commodities1){
//            if(detail.getStartNumber() > 0 || NumberUtil.isGreater(detail.getStartWeight(), BigDecimal.ZERO)){
//                currentCommodities.add(detail);
//            }
//            // 如果是非标品,并且订单重量大于0
//            if(NumberUtil.equals(detail.getStandard(), BigDecimal.ZERO) && NumberUtil.isGreater(detail.getStartWeight(), BigDecimal.ZERO)){
//                currentCommodities.add(detail);
//            }
            // 只有订单数量大于0 才可以
            if(detail.getStartNumber() > 0){
                currentCommodities.add(detail);
            }
        }
        if (CollectionUtils.isEmpty(currentCommodities)){
            throw new Exception("商品的初始数量/重量全是0，无法正常保存");
        }
        // 商品id集合
        List<Long> productIds = currentCommodities.stream().map(SalesOrderDetail::getCommodityId).collect(Collectors.toList());
//        // 判断商品是否有跨台账的情况
//        QueryWrapper<Products> queryWrapper = new QueryWrapper<>();
//        queryWrapper.in("id", productIds);
//        queryWrapper.groupBy("region_id");
        List<Products> regionCount = productsService.queryListByIds(productIds);
        Map<Integer, List<Products>> listMap = regionCount.stream().collect(Collectors.groupingBy(Products::getRegionId));
        Set<Integer> regionIds = listMap.keySet();
        if(regionIds.size() > 1){
            throw new Exception("商品跨台账，无法正常保存");
        }
        salesOrder.setRegionId(regionCount.get(0).getRegionId());
        // 商品重新负值
        salesOrder.setCommodities(currentCommodities);
        AddressBook addressBook = iAddressBookService.queryById(salesOrder.getCustomerId());
        if(ObjectUtil.isNull(addressBook)){
            throw new Exception("客户不存在");
        }
        salesOrder.setCustomerNameAlias(addressBook.getAlias());
        // 相同商品不能重复添加
        Map<String, List<SalesOrderDetail>> sodMap = new HashMap<>();
        for(SalesOrderDetail so : currentCommodities){
            String key = so.getCommodityId() + "-" + so.getSpecsId();
            if(sodMap.containsKey(key)){
                sodMap.get(key).add(so);
            }else{
                sodMap.put(key, new ArrayList<>(Collections.singletonList(so)));
            }
        }
        for(Map.Entry<String, List<SalesOrderDetail>> en : sodMap.entrySet()){
            List<SalesOrderDetail> details = en.getValue();
            if(CollectionUtil.isNotEmpty(details) && details.size() > 1){
                SalesOrderDetail salesOrderDetail = details.get(0);
                String commodityName = salesOrderDetail.getCommodityName();
                commodityName = commodityName + (StrUtil.isNotBlank(salesOrderDetail.getSpecsName()) ? "("+ salesOrderDetail.getSpecsName()+")" : "" );
                throw new Exception( commodityName + "不可以重复添加");
            }
        }
        // 商品总数
        Integer number = 0;
        // 商品总重
        BigDecimal weight = BigDecimal.ZERO;

        for (SalesOrderDetail orderDetail: currentCommodities) {
            orderDetail.setNumber(orderDetail.getStartNumber());
            BigDecimal weight_s = orderDetail.getStartWeight();
            orderDetail.setWeight(weight_s);
            
            number = number+orderDetail.getNumber();
            weight = weight.add(orderDetail.getWeight());
        }
        salesOrder.setNumber(number);
        salesOrder.setWeight(weight);
//        salesOrder.setOrderTime(new Date());
        if (salesOrder.getId() == null){
            // 新增入库采购收货主表
            salesOrder.setDocNo(CommonConstant.XSDH+ baseMapper.getNextCode());
            salesOrder.setState(1);
            save(salesOrder);
        }else {
            List<SalesOrderDetail> oldDetails = detailService.selectByOrderId(salesOrder.getId());
            for(SalesOrderDetail detail : oldDetails){
                Optional<SalesOrderDetail> optional = currentCommodities.stream().filter(d -> d.getCommodityId().equals(detail.getCommodityId())).findAny();
                // 如果现在的商品没有原来的商品，说明原来的商品已经被删除。此时需要把原来商品的走货库存恢复
                if(!optional.isPresent()){
                    List<SalesOrderDetailStock> detailStocks = detailStockService.selectByDetailId(detail.getId());
                    if(CollectionUtil.isNotEmpty(detailStocks)){
                        for(SalesOrderDetailStock ds : detailStocks){
                            log.info("{}在新的商品集合里没哟发现，说明已经被删除，需要恢复库存：数量-{} 重量-{}", detail.getCommodityName() + "("+detail.getStandard()+"公斤)", ds.getNumber(), ds.getWeight());
                            stockService.releaseStockByDetailId(ds.getDetailId());
                        }
                    }
                }
            }
            // 检查版本号是否过期
            SalesOrder existOrder = getById(salesOrder.getId());
            if(Objects.isNull(existOrder)){
                throw new Exception("订单不存在，修改失败.");
            }
            // 修改主表数据
            boolean success = updateById(salesOrder);
            if (!success) {
                throw new OptimisticLockingFailureException("更新失败，数据已被修改");
            }
        }
        // 入库采购收货主键
        Long mainId = salesOrder.getId();
        // 保存订单下明细
        saveDetailInfo(mainId, salesOrder);
        return R.data(mainId);
    }

    /**
     * 条件查询任务下达列表
     *
     * @param params
     * @return
     */
    @Override
    public List<SalesOrderTransmit> transmitList(SalesOrderTransmitPO po) {
        // 1. 查询走货时间是今天且状态是已确认的销售订单列表
        // 2. 根据1统计要货数量等信息
        // 3. 查询创建时间是今天的代办入库列表
        // 4. 根据3统计以下达任务信息
        // 5. 根据1统计商品的库存信息
        List<SalesOrderTransmit> transmitList = new ArrayList<>();
//        QueryWrapper<SalesOrder> soWrapper = new QueryWrapper<>();
//        soWrapper.eq("purchase_time", DateUtil.today());
//        soWrapper.in("state", Arrays.asList(1, 2, 3));
//        List<SalesOrder> soList = baseMapper.selectList(soWrapper);
//        if(CollectionUtil.isNotEmpty(soList)){
//            List<Long> mainIds = soList.stream().map(SalesOrder::getId).collect(Collectors.toList());
//            QueryWrapper<SalesOrderDetail> sodWrapper = new QueryWrapper<>();
//            sodWrapper.in("sales_id", mainIds);
//            if(ObjectUtil.isNotNull(params.get("category")) && StringUtils.isNotBlank(params.get("category").toString())){
//                sodWrapper.eq("category", String.valueOf(params.get("category")));
//            }
            List<SalesOrderDetail> sodList = baseMapper.selectDetailList(po);
//            for(SalesOrderDetail sod : sodList ){
//                Optional<SalesOrder> optional = soList.stream().filter(so -> so.getId().equals(sod.getSalesId())).findAny();
//                if(optional.isPresent()){
//                    sod.setCustomerName(optional.get().getCustomerName());
//                }
//            }
            // 按照商品id + 规格分组
            Map<String, List<SalesOrderDetail>> sodMap = new HashMap<>();
            for(SalesOrderDetail so : sodList){
                String key = so.getCommodityId() + "-" + so.getSpecsId();
                if(sodMap.containsKey(key)){
                    sodMap.get(key).add(so);
                }else{
                    sodMap.put(key, new ArrayList<>(Collections.singletonList(so)));
                }
            }
            // 设置代办交货的已下达数量
            Map<String, List<AgentDeliveryDetail>> addMap = getAgentOrderMap(po);
            // 设置打包加工的已下达数量
            Map<String, List<PackDeliveryDetail>> pddMap = getPackOrderMap(po);
            Map<String, List<Stock>> sdMap = new HashMap<>();
            // 根据商品ids查询库存列表
            List<Stock> stocks = stockService.stockList(sodList.stream().map(SalesOrderDetail::getCommodityId).collect(Collectors.toList()));
            for(Stock so : stocks){
                String key = so.getCommodityId() + "-" + so.getSpecsId();
                if(sdMap.containsKey(key)){
                    sdMap.get(key).add(so);
                }else{
                    sdMap.put(key, new ArrayList<>(Collections.singletonList(so)));
                }
            }
            for (Map.Entry<String, List<SalesOrderDetail>> en1 : sodMap.entrySet()){
                List<SalesOrderDetail> details = en1.getValue();
                SalesOrderTransmit transmit = new SalesOrderTransmit();
                BeanUtils.copyProperties(details.get(0), transmit);
                transmit.setNumber(details.stream().mapToInt(flow -> flow.getNumber()).sum());
                transmit.setWeight(BigDecimal.valueOf(details.stream().mapToDouble(flow -> flow.getWeight().doubleValue()).sum()));
                transmit.setStockNumber(stocks.stream().mapToInt(flow -> flow.getNumber()).sum());
                transmit.setStockWeight(BigDecimal.valueOf(stocks.stream().mapToDouble(flow -> flow.getWeight().doubleValue()).sum()));
                // 产品标志
                String goodsKey = en1.getKey();
                List<Stock> enStocks = CollectionUtil.isNotEmpty(sdMap.get(goodsKey)) ? sdMap.get(goodsKey) : new ArrayList<>();
                transmit.setStockNumber(enStocks.stream().mapToInt(flow -> flow.getNumber()).sum());
                transmit.setStockWeight(BigDecimal.valueOf(enStocks.stream().mapToDouble(flow -> flow.getWeight().doubleValue()).sum()));
                List<Map<String, String>> completes = new ArrayList<>();
                // 统计代办交货的下单数量/重量
                for (Map.Entry<String, List<AgentDeliveryDetail>> en2 : addMap.entrySet()){
                    List<AgentDeliveryDetail> detailList = addMap.get(goodsKey);
                    if(goodsKey.equalsIgnoreCase(en2.getKey())){
                        transmit.setCompleteNumber(detailList.stream().mapToInt(flow -> flow.getPlanNumber()).sum());
                        transmit.setCompleteWeight(BigDecimal.valueOf(detailList.stream().mapToDouble(flow -> flow.getPlanWeight().doubleValue()).sum()));
                        for(AgentDeliveryDetail detail : detailList){
                            Map<String, String> c = new HashMap<>();
                            c.put("agentName", detail.getAgentName());
                            c.put("number", detail.getPlanNumber()+"");
                            c.put("weight", detail.getPlanWeight()+"");
                            completes.add(c);
                        }
                    }
                }
                // 统计冷库加工的下单数量/重量
                for (Map.Entry<String, List<PackDeliveryDetail>> en2 : pddMap.entrySet()){
                    List<PackDeliveryDetail> detailList = pddMap.get(goodsKey);
                    if(goodsKey.equalsIgnoreCase(en2.getKey())){
                        int number = detailList.stream().mapToInt(flow -> flow.getNumber()).sum();
                        BigDecimal weight = BigDecimal.valueOf(detailList.stream().mapToDouble(flow -> flow.getWeight().doubleValue()).sum());
                        transmit.setCompleteNumber(transmit.getCompleteNumber() + number);
                        transmit.setCompleteWeight(NumberUtil.add(transmit.getCompleteWeight(), weight));
                        for(PackDeliveryDetail detail : detailList){
                            Map<String, String> c = new HashMap<>();
                            c.put("agentName", "秦明君");
                            c.put("number", detail.getNumber()+"");
                            c.put("weight", detail.getWeight()+"");
                            completes.add(c);
                        }
                    }
                }
                transmit.setCompletes(completes);
                transmit.setStocks(sdMap.get(goodsKey));
                transmit.setSurplusNumber(transmit.getNumber() - transmit.getCompleteNumber());
                transmit.setSurplusWeight(NumberUtil.sub(transmit.getWeight(), transmit.getCompleteWeight()));
                String remark = "";
                List<Map<String, Object>> remarkDetail = new ArrayList<>();
                for (SalesOrderDetail d : details){
                    remark = d.getCustomerName()+"("+d.getNumber()+"件) /" + remark;
                    Map<String, Object> rd = new HashMap<>();
                    rd.put("customerName", d.getCustomerName());
                    rd.put("number", d.getNumber());
                    remarkDetail.add(rd);
                }
                transmit.setRemark(remark);
                transmit.setRemarkDetail(remarkDetail);
                transmitList.add(transmit);
            }
//        }
        Collections.sort(transmitList, new Comparator<SalesOrderTransmit>() {
            final Comparator<Object> com = Collator.getInstance(java.util.Locale.CHINA);
            @Override
            public int compare(SalesOrderTransmit o1, SalesOrderTransmit o2) {
                int result = 0;
                try {
                    result = com.compare(o1.getCategory(), o2.getCategory());
                }catch (Exception e){
                    e.printStackTrace();
                }
                if(result == 0) {
                    result = com.compare(o1.getCommodityName(), o2.getCommodityName());
                }
                return result;
            }
        });
        return transmitList;
    }

    private Map<String, List<AgentDeliveryDetail>> getAgentOrderMap(SalesOrderTransmitPO po) {
        // 设置代办交货的已下达数量
        QueryWrapper<AgentDelivery> adWrapper = new QueryWrapper<>();
        adWrapper.between("create_time", DateUtil.beginOfDay(po.getStartTime()), DateUtil.endOfDay(po.getEndTime()));
        List<AgentDelivery> adList = agentDeliveryService.getBaseMapper().selectList(adWrapper);
        List<Long> adIds = adList.stream().map(AgentDelivery::getId).collect(Collectors.toList());
        // 按照商品id + 规格分组
        Map<String, List<AgentDeliveryDetail>> addMap = new HashMap<>();
        if(CollectionUtil.isNotEmpty(adIds)){
            QueryWrapper<AgentDeliveryDetail> addWrapper = new QueryWrapper<>();
            addWrapper.in("delivery_id", adIds);
            List<AgentDeliveryDetail> addList = agentDeliveryDetailService.getBaseMapper().selectList(addWrapper);
            for(AgentDeliveryDetail so : addList){
                String key = so.getCommodityId() + "-" + so.getSpecsId();
                AgentDelivery ad = adList.stream().filter(a -> a.getId().equals(so.getDeliveryId())).findAny().get();
                so.setAgentName(ad.getAgentName());
                if(addMap.containsKey(key)){
                    addMap.get(key).add(so);
                }else{
                    addMap.put(key, new ArrayList<>(Collections.singletonList(so)));
                }
            }
        }
        return addMap;
    }

    private Map<String, List<PackDeliveryDetail>> getPackOrderMap(SalesOrderTransmitPO po) {
        // 设置代办交货的已下达数量
        QueryWrapper<PackDelivery> adWrapper = new QueryWrapper<>();
        adWrapper.between("create_time", DateUtil.beginOfDay(po.getStartTime()), DateUtil.endOfDay(po.getEndTime()));
        // 0代表是从代办交货创建的生产单子
        adWrapper.eq("create_user_id", 0);
        List<PackDelivery> adList = packDeliveryService.getBaseMapper().selectList(adWrapper);
        List<Long> adIds = adList.stream().map(PackDelivery::getId).collect(Collectors.toList());
        // 按照商品id + 规格分组
        Map<String, List<PackDeliveryDetail>> addMap = new HashMap<>();
        if(CollectionUtil.isNotEmpty(adIds)){
            QueryWrapper<PackDeliveryDetail> addWrapper = new QueryWrapper<>();
            addWrapper.in("delivery_id", adIds);
            addWrapper.eq("detail_type", 1);
            List<PackDeliveryDetail> addList = packDeliveryDetailService.getBaseMapper().selectList(addWrapper);
            for(PackDeliveryDetail so : addList){
                String key = so.getCommodityId() + "-" + so.getSpecsId();
                if(addMap.containsKey(key)){
                    addMap.get(key).add(so);
                }else{
                    addMap.put(key, new ArrayList<>(Collections.singletonList(so)));
                }
            }
        }
        return addMap;
    }

    /**
     * 任务下达
     * @param po null
     * @return R
     * @author wrj
     * @since 2024/3/29 下午3:38
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R assignTask(SalesAssignTaskPO po) throws Exception {

        Map<String, SalesAssignDetailCommodityPO> map = new HashMap<>();
        // 根据选择的几个待办，生成几个入库的待办交货
        log.info(" 根据选择的几个待办，生成几个入库的待办交货 -- 开始");
        for (SalesAssignDetailPO assignDetailPO:po.getItems()) {
            // 如果代办名字是秦明君，则生成加工订单
            if("秦明君".equalsIgnoreCase(assignDetailPO.getAgentName())){
                extractedPack(assignDetailPO);
            }else{
                extractedAgent(po, map, assignDetailPO);
            }
        }
        // 根据商品循环更新订单下达表数据
        for (String key :map.keySet()) {
            SalesAssignDetailCommodityPO po1 = map.get(key);
            log.info("根据商品循环更新订单下达表数据:{}", JSON.toJSONString(po1));
            // 更新订单商品的下达数量，重量
            QueryWrapper<SalesOrderTransmit> wrapper_tr = new QueryWrapper<>();
            wrapper_tr.lambda().eq(SalesOrderTransmit::getCommodityId, po1.getCommodityId());

            if (po1.getSpecsId()== null){
                wrapper_tr.lambda().isNull(SalesOrderTransmit::getSpecsId);
            }else {
                wrapper_tr.lambda().eq(SalesOrderTransmit::getSpecsId, po1.getSpecsId());
            }
            SalesOrderTransmit transmit = transmitMapper.selectOne(wrapper_tr);
            if (transmit != null){
                transmit.setCompleteNumber(transmit.getCompleteNumber() + po1.getNumber());
                BigDecimal completeWeight = transmit.getCompleteWeight();
                completeWeight = completeWeight.add(po1.getWeight());
                transmit.setCompleteWeight(completeWeight);


                transmit.setSurplusNumber(transmit.getSurplusNumber() - po1.getNumber());
                // 剩余重量 = 本次重量-已下达重量
                BigDecimal surplusWeight = transmit.getSurplusWeight();
                surplusWeight = surplusWeight.subtract(po1.getWeight());
                transmit.setSurplusWeight(surplusWeight);
                log.info("下达成功后，更新已下达数，重量，未下达数，重量：{}", JSON.toJSONString(transmit));
                transmitMapper.updateById(transmit);

            }
        }

        return R.status(true);
    }

    private void extractedPack(SalesAssignDetailPO assignDetailPO) throws Exception {
        for (SalesAssignDetailCommodityPO commodityPO: assignDetailPO.getCommodities()) {
            // 如果数量==0并且重量等于0，那么肯定是废数据
            if(commodityPO.getWeight().compareTo(BigDecimal.ZERO) == 0 || commodityPO.getNumber() == 0){
                continue;
            }
            PackDelivery packDelivery = new PackDelivery();
            List<PackDeliveryDetail> finishCommodities = new ArrayList<>();
            PackDeliveryDetail pd = new PackDeliveryDetail();
            BeanUtils.copyProperties(commodityPO, pd);
            pd.setDetailType(1);
            finishCommodities.add(pd);
            packDelivery.setFinishCommodities(finishCommodities);
            packDelivery.setCommodities(new ArrayList<>());
            packDelivery.setMoney(BigDecimal.ZERO);
            // 0代表是任务下达的加工任务
            packDelivery.setCreateUserId(0L);
            packDelivery.setOrderTime(new Date());
            packDeliveryService.saveOrEdit(packDelivery);
        }
    }

    private void extractedAgent(SalesAssignTaskPO po, Map<String, SalesAssignDetailCommodityPO> map, SalesAssignDetailPO assignDetailPO) throws Exception {
        AgentDelivery agentDelivery = new AgentDelivery();
        agentDelivery.setOrderTime(po.getOrderTime());
        agentDelivery.setOrderSource(0); // 来源 销售订货
        agentDelivery.setAgentId(assignDetailPO.getAgentId());
        agentDelivery.setAgentName(assignDetailPO.getAgentName());
        agentDelivery.setMoney(BigDecimal.ZERO);
        // 下达任务，默认就是进入下达环节
        agentDelivery.setState(0);
        agentDelivery.setTeamArrears(BigDecimal.ZERO);
        agentDelivery.setRemark("来源于销售订货的任务下达");
        List<AgentDeliveryDetail> commodities = new ArrayList<>();
        for (SalesAssignDetailCommodityPO commodityPO: assignDetailPO.getCommodities()) {
            // 如果数量==0并且重量等于0，那么肯定是废数据
            if(commodityPO.getWeight().compareTo(BigDecimal.ZERO) == 0 && commodityPO.getNumber() == 0){
                log.info("{}的数量，重量全部是0。废数据", JSONObject.toJSONString(commodityPO));
                continue;
            }
            String k = commodityPO.getCommodityName()+commodityPO.getSpecsName();
            if (map.containsKey(k)){
                SalesAssignDetailCommodityPO po_v = map.get(k);
                // 更新数量
                Integer number = po_v.getNumber();
                number = number+commodityPO.getNumber();
                po_v.setNumber(number);
                // 更新重量
                BigDecimal weight = po_v.getWeight();
                weight = weight.add(commodityPO.getWeight());
                po_v.setWeight(weight);
                map.put(k, po_v);
            }else {
                map.put(k, commodityPO);
            }

            AgentDeliveryDetail deliveryDetail = new AgentDeliveryDetail();
            deliveryDetail.setOrderSource(0); // 来源 销售订货
            deliveryDetail.setCommodityId(commodityPO.getCommodityId());
            deliveryDetail.setCommodityName(commodityPO.getCommodityName());
            deliveryDetail.setSpecsId(commodityPO.getSpecsId());
            deliveryDetail.setSpecsName(commodityPO.getSpecsName());
            deliveryDetail.setStandard(commodityPO.getStandard());
            deliveryDetail.setPlanNumber(commodityPO.getNumber());
            deliveryDetail.setPlanWeight(commodityPO.getWeight());
            deliveryDetail.setNumber(commodityPO.getNumber());
            deliveryDetail.setWeight(commodityPO.getWeight());
            commodities.add(deliveryDetail);
        }
        agentDelivery.setCommodities(commodities);
        log.info("组装入库-待办交货后，准备进行保存：{}", JSON.toJSONString(agentDelivery));
        if (commodities.size() > 0 ){
            log.info("组装入库-待办交货后，商品不为空，开始进行保存：{}", JSON.toJSONString(agentDelivery));
            agentDeliveryService.saveOrEdit(agentDelivery);
        }
    }

    /**
     * 保存订单下明细
     * @param mainId
     * @param salesOrder
     * @return
     */
    private R saveDetailInfo(Long mainId, SalesOrder salesOrder) throws Exception {
        // 保存订单下明细
        log.info("保存订单下明细:{}", JSON.toJSONString(salesOrder.getDocNo()));
        List<SalesOrderDetail> commodities = salesOrder.getCommodities();
        // 查询改销售订单下的所有明细
        for (SalesOrderDetail deliveryDetail: commodities) {
            // 判断当前商品是不是在
            if (Objects.isNull(deliveryDetail.getId())){
                deliveryDetail.setSalesId(mainId);
                detailService.save(deliveryDetail);
            }else{
                deliveryDetail.setSalesId(mainId);
                detailService.updateById(deliveryDetail);
            }
            // 新的商品列表详情id集合
            List<Long> detailIds = commodities.stream().filter(detail -> Objects.nonNull(detail.getId())).
                    map(detail -> detail.getId()).collect(Collectors.toList());
            List<Long> oldIds = detailService.selectDetailIdByOrderId(mainId);
            for (Long id : oldIds){
                if(!detailIds.contains(id)){
                    detailService.delDetail(id);
                }
            }
        }
        return R.data(mainId);
    }

    /**
     * 销售订货下-走货
     * @param salesOrder null
     * @return R
     * @author wrj
     * @since 2024/3/27 下午4:35
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R submitSalesOrder(SalesOrder salesOrder) throws Exception {
        salesOrder.setState(1);
        updateById(salesOrder);
        // 明细id和原走货对照关系
        for (SalesOrderDetail detail:salesOrder.getCommodities()) {
            // 走货逻辑
            deliverySalesOrder(detail);
        }
        return R.data(salesOrder.getId());
    }

    /**
     * 销售走货
     * @param detail null
     * @return R
     * @author wrj
     * @since 2024/3/29 上午10:40
     */
    @Transactional(rollbackFor = Exception.class)
    public R deliverySalesOrder(SalesOrderDetail detail) throws Exception {
        // 验证销售订单是否已经发货，如果是，则只能何姐修改
//        SalesOut outOrder = salesOutService.selectByOrderId(detail.getSalesId());
//        if(Objects.nonNull(outOrder) && outOrder.getState() == 1){
//            // 当前操作人员
//            SysUserEntity user = (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
//            if(ObjectUtil.isNotNull(user) && "f006".equals(user.getUsername())){
//                log.info("当前登录用户是何姐，可以修改已发货订单的走货.");
//            }else{
//                throw new RuntimeException("订单已出库，如果修改请联系何姐.");
//            }
//        }

        QueryWrapper<SalesOrderDetailStock> wrapper = new QueryWrapper<>();
        wrapper.eq("detail_id", detail.getId());
        wrapper.gt("create_time", DateUtils.addMinutes(new Date(), -1));
        List<SalesOrderDetailStock> recentAdList = detailStockService.getBaseMapper().selectList(wrapper);
        if(CollectionUtil.isNotEmpty(recentAdList)){
            return R.fail(detail.getCommodityName() + "最近1分钟内已经走货了，请稍后重试");
        }
        SalesOrder salesOrder = getById(detail.getSalesId());
        Integer shiftNumber = 0;
        BigDecimal shiftWeight = BigDecimal.ZERO;
        if (CollectionUtils.isNotEmpty(detail.getStocks())){
            for (SalesOrderDetailStock detailStock:detail.getStocks()) {
                // 同时检验 非标商品走货是否 合规
                if(NumberUtil.equals(detail.getStandard(), BigDecimal.ZERO) && detailStock.getNumber() != 0 && NumberUtil.isLessOrEqual(detailStock.getWeight(), BigDecimal.ZERO)){
                    return R.fail("非标商品的走货数量必须大于0");
                }
                shiftNumber = shiftNumber+detailStock.getNumber();
                shiftWeight = shiftWeight.add(detailStock.getWeight());
            }
            // 修改对应商品明细的走货数量
            detail.setShiftNumber(shiftNumber);
            detail.setShiftWeight(shiftWeight);
        }else{
            return R.fail(detail.getCommodityName() + "没有选择库存，不可以走货哦");
        }
        log.info("{}的走货数量{}-走货重量{}", detail.getId(), detail.getShiftNumber(), detail.getShiftWeight());
        detailService.updateById(detail);
        // 根据详情查询主表信息
//        SalesOrderDetail sod = detailService.getById(detail.getId());
//        getById(sod.get)

        // 旧（上次）走货的走货库存对照map
        Map<Long, SalesOrderDetailStock> toMap = new HashMap<>();
        // 修改前旧商品库存对照数据
        List<SalesOrderDetailStock> detailStocks = detailStockService.getBaseMapper().selectList(Wrappers.<SalesOrderDetailStock>query().lambda().eq(SalesOrderDetailStock::getDetailId, detail.getId()));
        log.info("查询原商品下走货的商品库存对照数据：{}", JSON.toJSONString(detailStocks));
        if (CollectionUtils.isNotEmpty(detailStocks)){
            toMap = detailStocks.stream().collect(Collectors.toMap(SalesOrderDetailStock::getId, orderDetail -> orderDetail));
        }

        List<Stock> stockList = new ArrayList<>();

        // 循环本次 走货库存关系列表
        for (SalesOrderDetailStock detailStock : detail.getStocks()) {
            BigDecimal balanceNumber = BigDecimal.ZERO;
            detailStock.setDetailId(detail.getId());

            // 根据库存id查询需更新的库存表数据
            Stock stock = stockService.getById(detailStock.getStockId());
//            if(ObjectUtil.isNull(stock) || stock.getNumber()<=0 || NumberUtil.isLess(stock.getWeight(), BigDecimal.ZERO)){
//                throw new Exception("选择的库存已经耗尽，刷新页面后重试");
//            }
            if(!stock.getCommodityId().equals(detail.getCommodityId())){
                throw new Exception("选择的库存已经耗尽，刷新页面后重试");
            }
            log.info("走货：根据库存id查询原始库存：{}", JSON.toJSONString(stock));
            BigDecimal changeNum = NumberUtil.equals(stock.getStandard(), BigDecimal.ZERO) ? detailStock.getWeight() : new BigDecimal(detailStock.getNumber());
            SalesOrderDetailStock old_d = new SalesOrderDetailStock();
            // map大于0 ，说明这次触发不是首次走货，之前肯定走货过，这次是属于又点击走货，
            int stockNumber = stock.getNumber() - detailStock.getNumber();
            if (toMap.size() > 0){
                // detailStock.getId()为空 意思是之前的走货没选过这个库存，这次是新选的所以没有id
                if (detailStock.getId() == null){
                    if(detailStock.getNumber() > 0 || NumberUtil.isGreater(detailStock.getWeight(), BigDecimal.ZERO)){
                        log.info("商品名：{} 库存数量:{} 走货数量{} 剩余数量：{}", stock.getCommodityName(), stock.getNumber(), detailStock.getNumber(), stockNumber);
                        // 差额数= 本次-旧数量
                        BigDecimal stockWeight = stock.getWeight();
                        // 库存数量和重量 减去 本次走货选择的数量和重量
                        stockWeight = stockWeight.subtract(detailStock.getWeight());
                        stock.setNumber(stockNumber);
                        stock.setWeight(stockWeight);
//                        balanceNumber = detailStock.getNumber();
                        balanceNumber = NumberUtil.equals(stock.getStandard(), BigDecimal.ZERO) ? detailStock.getWeight() : new BigDecimal(detailStock.getNumber());
                    }else{
                        log.info("{}的数量/重量都是0，属于废数据", detailStock.getDetailId());
                    }
                }else {
                    // id不为空，说明是上次走货选的是这个，类似于上次走货选的这个库存走的3个，这次还是它，走货改成了5个
                    old_d = toMap.get(detailStock.getId());
                    // 差额数和重量= 本次走货数和重量-上次旧走货数量和重量
                    Integer number_balance =detailStock.getNumber() - old_d.getNumber();
                    stockNumber = stock.getNumber() - number_balance;
                    log.info("商品名：{} 库存数量:{} 原走货数量:{} 现在走货数量:{} 剩余数量：{}", stock.getCommodityName(), stock.getNumber(), old_d.getNumber(), detailStock.getNumber(), stockNumber);
                    BigDecimal weight__balance = detailStock.getWeight();
                    weight__balance = weight__balance.subtract(old_d.getWeight());
                    BigDecimal stockWeight = stock.getWeight();
                    stockWeight = stockWeight.subtract(weight__balance);
                    stock.setNumber(stockNumber);
                    stock.setWeight(stockWeight);
//                    balanceNumber = number_balance;
                    balanceNumber = NumberUtil.equals(stock.getStandard(), BigDecimal.ZERO) ? weight__balance : new BigDecimal(number_balance);
                }
                // toMap为空，说明是首次走货
            }else {
                log.info("商品名：{} 库存数量:{} 走货数量{} 剩余数量：{}", stock.getCommodityName(), stock.getNumber(), detailStock.getNumber(), stockNumber);
                // 差额数量和重量= 库存数量和重量-本次走货数量和重量
                BigDecimal stockWeight = stock.getWeight();
                stockWeight = stockWeight.subtract(detailStock.getWeight());
                stock.setNumber(stockNumber);
                stock.setWeight(stockWeight);
//                balanceNumber = detailStock.getNumber();
                balanceNumber = NumberUtil.equals(stock.getStandard(), BigDecimal.ZERO) ? detailStock.getWeight() : new BigDecimal(detailStock.getNumber());
            }
//            if (stock.getNumber() > 0 &&
//                    stock.getWeight().compareTo(BigDecimal.ZERO) > 0){
                log.info("走货：根据库存id查询修改后库存：{}", JSON.toJSONString(stock));
                stockList.add(stock);
                if(NumberUtil.isGreater(balanceNumber, BigDecimal.ZERO)){
                    iStockFlowService.addStockFlow(stock, Constant.StockFlowType.SALE_OUT.getValue(),  balanceNumber, salesOrder.getDocNo(), salesOrder.getCustomerName(), salesOrder.getOrderTime());
                } else if (NumberUtil.isLess(balanceNumber, BigDecimal.ZERO)) {
                    iStockFlowService.addStockFlow(stock, Constant.StockFlowType.SALE_RETURN_IN.getValue(),  balanceNumber.abs(), salesOrder.getDocNo(), salesOrder.getCustomerName(), salesOrder.getOrderTime());
                }


//            }else {
                log.info("销售出库商品出库删除库存，库存剩余数量：{}，库存剩余重量{}", stock.getNumber(), stock.getWeight());
//                stockService.removeById(stock);
//            }
        }
        for(Stock stock : stockList){
            if(stock.getNumber() < 0 || NumberUtil.isLess(stock.getWeight(), BigDecimal.ZERO)){
                throw new Exception(stock.getCommodityName() + "库存不够走货数量，请选择其他库存或者修改走货数量");
            }
        }
        List<SalesOrderDetailStock> stocks = new ArrayList<>();
        for(SalesOrderDetailStock detailStock : detail.getStocks()){
            Integer inNumber = detailStock.getNumber();
            BigDecimal inWeight = detailStock.getWeight();
            if((ObjectUtil.isNotNull(inNumber) && inNumber != 0) || (ObjectUtil.isNotNull(inWeight) && !NumberUtil.equals(inWeight, BigDecimal.ZERO))){
                detailStock.setOrderId(salesOrder.getId());
                detailStock.setType(0);
                stocks.add(detailStock);
            }else{
                if(ObjectUtil.isNotNull(detailStock.getId())){
                    detailStockService.deleteById(detailStock.getId());
                }
            }
        }
        detailStockService.saveOrUpdateBatch(stocks);
        // 批量更新库存
        stockService.updateBatchById(stockList);
        // 影响销售出库单
        effectSalesOut(detail);
        // 开始计算成本
        log.info("{}走货，影响出库单成本", JSONObject.toJSONString(detail));
        salesOutService.checkOrderCostByOrderId(detail.getSalesId());
        return R.data(detail.getId());
    }

    /**
     * 走货要可能影响销售出库
     * @param detail
     */
    @Deprecated
    private void effectSalesOut(SalesOrderDetail detail) {
        // 如果已经存在销售出库单，说明已经发货。此时需要谨慎的修改出库单的出库数据，并且 todo 通知何姐
        SalesOut salesOut = salesOutService.selectByOrderId(detail.getSalesId());
        if(Objects.nonNull(salesOut) && salesOut.getState() == 0){
            // 目前的销售出库单商品列表
            List<SalesOutDetail> outDetails = iSalesOutDetailService.selectBySalesId(salesOut.getId());
            Map<String, SalesOutDetail> detailMap = new HashMap<>();
            for(SalesOutDetail sd : outDetails){
                String key = sd.getCommodityId() + "-" + sd.getSpecsId();
                detailMap.put(key, sd);
            }
            Set<String> keys = detailMap.keySet();
            String nowKey = detail.getCommodityId() + "-" + detail.getSpecsId();
            if(keys.contains(nowKey)){
                SalesOutDetail updater = new SalesOutDetail();
                updater.setId(detailMap.get(nowKey).getId());
                updater.setNumber(detail.getShiftNumber());
                updater.setWeight(detail.getShiftWeight());
                iSalesOutDetailService.updateById(updater);
            }else{
                SalesOutDetail saver = new SalesOutDetail();
                BeanUtils.copyProperties(detail, saver);
                saver.setSalesId(salesOut.getId());
                saver.setNumber(detail.getShiftNumber());
                saver.setWeight(detail.getShiftWeight());
                iSalesOutDetailService.save(saver);
            }
        }
    }


    /**
     * 删除销售订货
     * @param id null
     * @return R
     * @author wrj
     * @since 2024/3/27 下午4:35
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R deleteSalesOrder(Long id) throws Exception {
        SalesOrder salesOrder = baseMapper.selectById(id);
        if (salesOrder == null){
            throw new Exception("订单不存在");
        }
        if (salesOrder.getState() == 3){
            throw new Exception("订单已完成 不允许删除");
        }
        List<SalesOrderDetail> details = detailService.selectByOrderId(id);
        for(SalesOrderDetail detail : details){
            if(detail.getShiftNumber() > 0 || NumberUtil.isGreater(detail.getShiftWeight(), BigDecimal.ZERO)){
                throw new Exception(detail.getCommodityName() + "已经走货，请归还库存后再次删除");
            }
        }
        baseMapper.deleteById(id);
        deleteMethod(salesOrder);
        return R.status(true);
    }

    /**
     * 完成销售订货
     * @param id null
     * @return R
     * @author wrj
     * @since 2024/3/29 上午11:48
     */
    @Override
    public R competeSalesOrder(Long id) throws Exception {
        SalesOrder salesOrder = baseMapper.selectById(id);
        if (salesOrder == null){
            throw new Exception("订单不存在");
        }
        salesOrder.setState(3);
        updateById(salesOrder);
        return R.status(true);
    }

    @Override
    public List<SalesOrderDetail> lastOrder(Long customerId) {
        List<SalesOrderDetail> result = new ArrayList<>();
        List<SalesOrderDetail> details = new ArrayList<>();
        QueryWrapper<SalesOrder> orderWrapper = new QueryWrapper();
        orderWrapper.eq("customer_id", customerId);
        orderWrapper.orderByDesc("create_time");
        List<SalesOrder> list = this.baseMapper.selectList(orderWrapper);
        if(CollectionUtil.isNotEmpty(list)){
            SalesOrder salesOrder = list.get(0);
            QueryWrapper<SalesOrderDetail> detailQuery = new QueryWrapper();
            detailQuery.eq("sales_id", salesOrder.getId());
            detailQuery.groupBy("commodity_id", "specs_Id");
            detailQuery.orderByAsc("sort", "id");
            details = detailService.getBaseMapper().selectList(detailQuery);
        }
        if(CollectionUtil.isNotEmpty(details)){
            List<Long> productIds = details.stream().map(SalesOrderDetail::getCommodityId).collect(Collectors.toList());
            // 这里把商品过滤下，已经被禁用的就筛掉
            List<Products> productsList = productsService.queryListByIds(productIds);
            productIds = productsList.stream().map(Products::getId).collect(Collectors.toList());
            List<ProductSpec> specList = productSpecService.queryByProductIds(productIds);
            if(CollectionUtil.isNotEmpty(specList)){
                Map<Long, List<ProductSpec>> specMap = specList.stream().collect(Collectors.groupingBy(ProductSpec::getProducerId));
                for(Map.Entry<Long, List<ProductSpec>> en : specMap.entrySet()){
                    long productId = en.getKey();
                    List<ProductSpec> specs = en.getValue();
                    Optional<SalesOrderDetail> optional = details.stream().filter(detail -> detail.getCommodityId().equals(productId)).findAny();
                    if(optional.isPresent()){
                        optional.get().setSpecList(specs);
                    }
                }
            }
            for(SalesOrderDetail dd : details){
                if(productIds.contains(dd.getCommodityId())){
                    dd.setCustomerName(list.get(0).getCustomerName());
                    dd.setNumber(0);
                    dd.setStartNumber(0);
                    dd.setShiftNumber(0);
                    dd.setStockNumber(0);
                    dd.setWeight(BigDecimal.ZERO);
                    dd.setStockWeight(BigDecimal.ZERO);
                    dd.setShiftWeight(BigDecimal.ZERO);
                    dd.setShiftWeight(BigDecimal.ZERO);
                    result.add(dd);
                }
            }
        }
        return result;
    }

    @Override
    public List<SalesOrderDetail> relateOrder(Long customerId) {
        List<SalesOrderDetail> result = new ArrayList<>();
        List<SalesOrderDetail> details = new ArrayList<>();
        QueryWrapper<SalesOrder> orderWrapper = new QueryWrapper();
        orderWrapper.eq("customer_id", customerId);
        orderWrapper.gt("order_time", DateUtil.offsetDay(new Date(), -60));
        orderWrapper.orderByDesc("create_time");
        List<SalesOrder> list = this.baseMapper.selectList(orderWrapper);
        if(CollectionUtil.isNotEmpty(list)){
//            SalesOrder salesOrder = list.get(0);
            List<Long> orderIds = list.stream().map(el -> el.getId()).collect(Collectors.toList());
            QueryWrapper<SalesOrderDetail> detailQuery = new QueryWrapper();
            detailQuery.in("sales_id", orderIds);
//            detailQuery.groupBy("commodity_id", "specs_Id");
            detailQuery.orderByDesc("create_time");
            details = detailService.getBaseMapper().selectList(detailQuery);
        }
        if(CollectionUtil.isNotEmpty(details)){
            // 商品id集合
            List<Long> productIds = details.stream().map(d -> d.getCommodityId()).collect(Collectors.toList());
            List<Products> productsList = productsService.queryListByIds(productIds);
            List<ProductSpec> specList = productSpecService.queryByProductIds(productIds);
            if(CollectionUtil.isNotEmpty(specList)){
                Map<Long, List<ProductSpec>> specMap = specList.stream().collect(Collectors.groupingBy(ProductSpec::getProducerId));
                for(Map.Entry<Long, List<ProductSpec>> en : specMap.entrySet()){
                    long productId = en.getKey();
                    List<ProductSpec> specs = en.getValue();
                    Optional<SalesOrderDetail> optional = details.stream().filter(detail -> detail.getCommodityId().equals(productId)).findAny();
                    if(optional.isPresent()){
                        optional.get().setSpecList(specs);
                    }
                }
            }
            Map<String, SalesOrderDetail> detailMap = new HashMap<>();
            List<SalesOrderDetail> temD = new ArrayList<>();
            for(SalesOrderDetail dd : details){
                Optional<Products> products = productsList.stream().filter(detail -> detail.getId().equals(dd.getCommodityId())).findAny();
                if(!products.isPresent()){
                    continue;
                }
                dd.setCommodityName(products.get().getCommonName());
                dd.setCommodityCode(products.get().getCommonCode());
                dd.setCustomerName(list.get(0).getCustomerName());
                dd.setOrderTime(list.get(0).getOrderTime());
                dd.setNumber(0);
                dd.setStartNumber(0);
                dd.setShiftNumber(0);
                dd.setStockNumber(0);
                dd.setWeight(BigDecimal.ZERO);
                dd.setStockWeight(BigDecimal.ZERO);
                dd.setStartWeight(BigDecimal.ZERO);
                dd.setShiftWeight(BigDecimal.ZERO);
                temD.add(dd);
            }
            for(SalesOrderDetail dd : temD){
                String specsName = StrUtil.isBlank(dd.getSpecsName()) ? "" : dd.getSpecsName();
                String commodityKey = dd.getCommodityId() + "-" + specsName;
                if(!detailMap.containsKey(commodityKey)){
                    detailMap.put(commodityKey, dd);
                }
            }
            for(Map.Entry<String, SalesOrderDetail> en : detailMap.entrySet()){
                result.add(en.getValue());
            }
        }
        return result;
    }

    @Override
    public R updateRemark(SalesOrder po) {
        SalesOrder updater = new SalesOrder();
        updater.setId(po.getId());
        updater.setRemark(po.getRemark());
        Integer res = this.getBaseMapper().updateById(updater);
        return R.data(res);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R oneClickShipping(Long salesOrderId) throws Exception {
        SalesOrder order = baseMapper.selectById(salesOrderId);
        if(ObjectUtil.isNull(order)){
            throw new RuntimeException("销售订单不存在");
        }
        List<SalesOrderDetail> details = detailService.selectByOrderId(salesOrderId);
        if(CollectionUtil.isEmpty(details)){
            throw new RuntimeException("销售订单里没有商品");
        }
//        // 验证商品是否实际已经走货
//        for(SalesOrderDetail detail : details){
//            if(detail.getShiftNumber() > 0 || NumberUtil.isGreater(detail.getShiftWeight(), BigDecimal.ZERO)){
//                throw new RuntimeException(detail.getCommodityName() + "已经走货了，不可以使用一键走货");
//            }
//        }
//        // 验证商品库存是否足够
//        Map<Long, List<Stock>> stockMap = new HashMap<>();
//        for(SalesOrderDetail detail : details){
//            if(detail.getStartNumber() == 0 && NumberUtil.equals(detail.getStartWeight(), BigDecimal.ZERO)){
//                log.info(detail.getCommodityName() + "要求的数量/重量都是零，无需查看库存");
//                continue;
//            }
//            // 合适的库存
//            List<Stock> existStock = stockService.getStocks(true, detail.getCommodityName(), detail.getStandard(), detail.getCommodityId(), detail.getSpecsId());
//            log.info(detail.getCommodityName() + "查找到的库存有：" + JSONArray.toJSONString(existStock));
//            // 当前的库存数量
//            Integer existNumber = existStock.stream().mapToInt(Stock::getNumber).sum();
//            // 当前的库存重量
//            BigDecimal existWeight = existStock.stream().map(Stock::getWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
//            // 如果是不标称的商品 就对比重量，反之对比数量
//            if(NumberUtil.equals(detail.getStandard(), BigDecimal.ZERO) && NumberUtil.isGreater(detail.getStartWeight(), existWeight)){
//                throw new RuntimeException(detail.getCommodityName() + "需要 " + detail.getStartWeight() + "公斤,但是库存只有" + existWeight + "公斤");
//            }
//            if(!NumberUtil.equals(detail.getStandard(), BigDecimal.ZERO) && detail.getStartNumber() > existNumber){
//                throw new RuntimeException(detail.getCommodityName() + "需要 " + detail.getStartNumber() + "件,但是库存只有" + existNumber + "件");
//            }
////            stockMap.put(detail.getId(), existStock);
//        }
        // 开始走货
        for(SalesOrderDetail detail : details){
            if(detail.getStartNumber() == 0 && NumberUtil.equals(detail.getStartWeight(), BigDecimal.ZERO)){
                log.info(detail.getCommodityName() + "要求的数量/重量都是零，无需查看走货");
                continue;
            }
            if(detail.getShiftNumber() > 0 || NumberUtil.isGreater(detail.getShiftWeight(), BigDecimal.ZERO)){
                log.info(detail.getCommodityName() + "已经走货了，无需再次走货");
                continue;
            }
            List<Stock> allStock = stockService.getStocks(true, detail.getCommodityName(), detail.getStandard(), detail.getCommodityId(), detail.getSpecsId());
            // 筛选数量大于0 或者重量大于0的库存
            List<Stock> existStock = allStock.stream().filter(ma -> (ma.getNumber() > 0 || NumberUtil.isGreater(ma.getWeight(), BigDecimal.ZERO))).collect(Collectors.toList());
            log.info(detail.getCommodityName() + "查找到的库存有：" + JSONArray.toJSONString(existStock));
            // 当前的库存数量
            Integer existNumber = existStock.stream().mapToInt(Stock::getNumber).sum();
            // 当前的库存重量
            BigDecimal existWeight = existStock.stream().map(Stock::getWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 如果是不标称的商品 就对比重量，反之对比数量.如果不够数 那么跳过处理下一条数据
            if(NumberUtil.equals(detail.getStandard(), BigDecimal.ZERO) && NumberUtil.isGreater(detail.getStartWeight(), existWeight)){
                log.info(detail.getCommodityName() + "需要 " + detail.getStartWeight() + "公斤,但是库存只有" + existWeight + "公斤");
                continue;
            }
            if(!NumberUtil.equals(detail.getStandard(), BigDecimal.ZERO) && detail.getStartNumber() > existNumber){
                log.info(detail.getCommodityName() + "需要 " + detail.getStartNumber() + "件,但是库存只有" + existNumber + "件");
                continue;
            }
            List<SalesOrderDetailStock> actStocks = new ArrayList<>();
            if(NumberUtil.equals(detail.getStandard(), BigDecimal.ZERO)){
                // 剩余走货重量
                BigDecimal balanceWeight = detail.getStartWeight();
                for(Stock stock : existStock){
                    if(NumberUtil.isGreaterOrEqual(BigDecimal.ZERO, balanceWeight)){
                        break;
                    }
                    // 该库存走货重量
                    BigDecimal thisWeight = NumberUtil.min(balanceWeight, stock.getWeight());

                    SalesOrderDetailStock ds = new SalesOrderDetailStock();
                    ds.setStockId(stock.getId());
                    ds.setWeight(thisWeight);
                    ds.setNumber(0);
                    actStocks.add(ds);
                    balanceWeight = NumberUtil.sub(balanceWeight, thisWeight);
                    log.info("{}走了{}公斤还差{}公斤", stock.getId(), thisWeight, balanceWeight);
                }
            }else{
                // 剩余走货数量
                Integer balanceNumber = detail.getStartNumber();
                for(Stock stock : existStock){
                    if(balanceNumber <= 0){
                        break;
                    }
                    // 该库存走货数量
                    Integer thisNumber = NumberUtil.min(balanceNumber, stock.getNumber());
                    SalesOrderDetailStock ds = new SalesOrderDetailStock();
                    ds.setStockId(stock.getId());
                    ds.setNumber(thisNumber);
                    ds.setWeight(NumberUtil.mul(thisNumber, detail.getStandard()));
                    actStocks.add(ds);
                    balanceNumber = balanceNumber - thisNumber;
                    log.info("{}走了{}件还差{}件", stock.getId(), thisNumber, balanceNumber);
                }
            }
            detail.setStocks(actStocks);
            deliverySalesOrder(detail);
        }
        return R.success("");
    }

    @Override
    public R noCostWeightList(NoCostWeightListPO po) throws Exception {
        IPage<NoCostWeightListVO> iPage =  new Page<>(po.getPageCurrent(), po.getPageSize());
        IPage<NoCostWeightListVO> result = this.baseMapper.noCostWeightList(iPage, po);
        return R.data(result);
    }

    @Override
    public R updateSalesOrder(SalesOrder salesOrder) throws Exception {
        // 验证销售订单是否已经发货，如果是，则不能修改
        SalesOut outOrder = salesOutService.selectByOrderId(salesOrder.getId());
        if(Objects.nonNull(outOrder) && outOrder.getState() == 1){
            throw new RuntimeException("订单已出库，如果修改请联系出库管理人员.");
        }
        return saveSalesOrder(salesOrder);
    }

    @Override
    public R confirmSalesOrder(SalesOrder salesOrder) throws Exception {
        // 验证销售订单是否已经发货，如果是，则不能修改
        SalesOut outOrder = salesOutService.selectByOrderId(salesOrder.getId());
        if(Objects.nonNull(outOrder) && outOrder.getState() == 1){
            throw new RuntimeException("订单已出库，如果修改请联系出库管理人员.");
        }
        return saveSalesOrder(salesOrder);
    }


    /**
     * 删除主方法
     * @param salesOrder
     * @return
     */
    private R deleteMethod(SalesOrder salesOrder) throws Exception {
        QueryWrapper<SalesOrderDetail> detailQueryWrapper = new QueryWrapper();
        detailQueryWrapper.eq("sales_id", salesOrder.getId());
        List<SalesOrderDetail> orderDetails = detailService.getBaseMapper().selectList(detailQueryWrapper);
        if (CollectionUtils.isNotEmpty(orderDetails)){
            List<Long> detailIds = orderDetails.stream().map(SalesOrderDetail::getId).collect(Collectors.toList());


            QueryWrapper<SalesOrderDetail> queryWrapper = new QueryWrapper();
            queryWrapper.eq("sales_id", salesOrder.getId());
            log.info("删除销售订货商品明细");
            detailService.getBaseMapper().delete(queryWrapper);


            QueryWrapper<SalesOrderDetailStock> stockQueryWrapper = new QueryWrapper<>();
            stockQueryWrapper.in("detail_id", detailIds);
            log.info("删除销售订货商品下的库存关系表数据");
            detailStockService.getBaseMapper().delete(stockQueryWrapper);

        }
        return R.status(true);
    }

    @Override
    public List<Map<String, String>> statisticTask(SalesOrderTransmitPO po){
        List<Map<String, String>> dataList = new ArrayList<>();
        List<SalesOrderDetail> sodList = baseMapper.selectDetailList(po);
        if(CollectionUtil.isNotEmpty(sodList)){
            List<String> customers = sodList.stream().map(SalesOrderDetail::getCustomerName).collect(Collectors.toList());
            log.info("----------> abc{}", JSONArray.toJSONString(customers));
            Map<String, String> lineOne = new LinkedHashMap<>();
            lineOne.put("category", "种类");
            lineOne.put("commodityName", "名称");
            for(String customer : customers){
                lineOne.put(customer, customer);
            }
            lineOne.put("totalNumber", "数量合计");
            lineOne.put("actualNumber", "实际加工");
            lineOne.put("balanceNumber", "当日余货");
            lineOne.put("remark", "特别备注");
            lineOne.put("tags", "标签要求");
            dataList.add(lineOne);
            Map<String, String> lineTwo = new LinkedHashMap<>();
            lineTwo.put("category", "");
            lineTwo.put("commodityName", "车辆类型");
            for(String customer : customers){
                lineOne.put(customer, customer);
            }
            lineTwo.put("totalNumber", "");
            lineTwo.put("actualNumber", "");
            lineTwo.put("balanceNumber", "");
            lineTwo.put("remark", "");
            lineTwo.put("tags", "");
            dataList.add(lineTwo);
            Map<String, String> lineThree = new LinkedHashMap<>();
            lineThree.put("category", "");
            lineThree.put("commodityName", "发车时间");
            for(String customer : customers){
                lineOne.put(customer, customer);
            }
            lineThree.put("totalNumber", "");
            lineThree.put("actualNumber", "");
            lineThree.put("balanceNumber", "");
            lineThree.put("remark", "");
            lineThree.put("tags", "");
            dataList.add(lineThree);
            Map<Long, Map<Long, List<SalesOrderDetail>>> salesOrderMap = sodList.stream().collect(Collectors.groupingBy(SalesOrderDetail::getCommodityId,Collectors.groupingBy(SalesOrderDetail::getSalesId)));
            for(Map.Entry<Long, Map<Long, List<SalesOrderDetail>>> entry : salesOrderMap.entrySet()){
                for(Map.Entry<Long, List<SalesOrderDetail>> dEntry : entry.getValue().entrySet()){
                    List<SalesOrderDetail> detailList = dEntry.getValue();
                    SalesOrderDetail detail = detailList.get(0);
//                    for(SalesOrderDetail detail : detailList){
                        Map<String, String> data = new LinkedHashMap<>();
                        data.put("category", detail.getCategory());
                        String commodityName = detail.getCommodityName();
                        if(ObjectUtil.isNotNull(detail.getSpecsId())){
                            commodityName = commodityName + "(" + detail.getSpecsName() +")";
                        }
                        data.put("commodityName", commodityName);
                        for(String customer : customers){
                            List<SalesOrderDetail> customerOrders = detailList.stream().filter(el -> el.getCustomerName().equals(customer)).collect(Collectors.toList());
                            int sum = customerOrders.stream().mapToInt(SalesOrderDetail::getNumber).sum();
                            data.put(customer, sum == 0 ? "" : sum + "");
                        }
                        data.put("totalNumber", detailList.stream().mapToInt(SalesOrderDetail::getNumber).sum() + "");
                        data.put("stockNumber", "");
                        data.put("actualNumber", "");
                        data.put("balanceNumber", "");
                        data.put("remark", "");
                        data.put("tags", "");
                        dataList.add(data);
//                    }
                }
            }
        }
        return dataList;
    }
    
    @Override
    public IPage<CustomerPurchaseAnalysisVO> analyzeCustomerPurchase(CustomerPurchaseAnalysisPO po) {
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<CustomerPurchaseAnalysisVO> page = 
            new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(po.getPage(), po.getLimit());
        
        // 先获取总记录数
        int total = this.baseMapper.countCustomerPurchase(po);
        page.setTotal(total);
        
        // 再获取数据
        IPage<CustomerPurchaseAnalysisVO> result = this.baseMapper.analyzeCustomerPurchase(page, po);
        
        // 手动排序结果
        List<CustomerPurchaseAnalysisVO> records = result.getRecords();
        records.sort((a, b) -> {
            // 首先按客户ID排序
            int customerCompare = a.getCustomerId().compareTo(b.getCustomerId());
            if (customerCompare != 0) {
                return customerCompare;
            }
            // 然后按采购次数降序排序
            int purchaseCountCompare = b.getPurchaseCount().compareTo(a.getPurchaseCount());
            if (purchaseCountCompare != 0) {
                return purchaseCountCompare;
            }
            // 最后按总数量降序排序
            return b.getTotalNumber().compareTo(a.getTotalNumber());
        });
        result.setRecords(records);
        return result;
    }
}
